/*
* Copyright 2005-2008 Pulse Technologies. Tutti i diritti riservati.
*/
package org.obsidianrad.server.services.user.rolemanager;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.obsidianrad.server.services.obj2db.dao.GenericProxy;
import org.obsidianrad.server.services.user.context.IContextManager;
import org.obsidianrad.utils.Constant.ObsidianOperations;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;

/**
 * 
 * @author Eligio Colutta
 * @version $Rev: 22 $
 * @lastautorcommit $Author: eliosh $
 * @lastdatecommit $Date: 2010-01-07 13:57:50 +0100(gio, 07 gen 2010) $
 */
public final class RoleManagerContext extends RoleManager {


	private IContextManager contextManager;
	private Map<Integer, List<String>> roleByContext;
	private List<Integer> contextIds;
	
	public RoleManagerContext(){
		roleByContext = new HashMap<Integer, List<String>>();
	}
	
	public Map<Integer, GrantedAuthority[]> getGrantedAuthoritiesMapByContext(){
		Map<Integer, GrantedAuthority[]> retVal = new HashMap<Integer, GrantedAuthority[]>();
		
		List<Integer> contextIds = contextManager.getContextIds();
		for(Integer i : contextIds){
			retVal.put(i, getGrantedAuthoritiesByContext(i));
		}
		
		return retVal;
	}
	
	public GrantedAuthority[] getGrantedAuthoritiesByContext(Integer context){
		List<String> localRoles = this.getRoles().get(context);
		GrantedAuthority[] retVal = new GrantedAuthority[localRoles.size()];
		int i=0;
		for(String role : localRoles){
			retVal[i++] = new GrantedAuthorityImpl(role);
		}
		return retVal;

	}
	
	public GrantedAuthority[] getGrantedAuthorities(){
		
		List<String> localRoles = new ArrayList<String>();
		
		Map<Integer, List<String>> roles = this.getRoles();
		Iterator<Integer> iterator = roles.keySet().iterator();
		while(iterator.hasNext()){
			Integer cid = iterator.next();
			localRoles.addAll(roles.get(cid));
		}
		
		GrantedAuthority[] retVal = new GrantedAuthority[localRoles.size()];
		int i=0;
		for(String role : localRoles){
			retVal[i++] = new GrantedAuthorityImpl(role);
		}
		return retVal;
	}
	
	private Map<Integer, List<String>> getRoles(){
		return getRoles(false);
	}
	
	private Map<Integer, List<String>> getRoles(boolean reset){
		if(reset || roleByContext.size()==0){
			getRolesBySpringContext();
		}
		return roleByContext;
	}
	
	@SuppressWarnings("unchecked")
	private void getRolesBySpringContext(){
		Map<String, GenericProxy> beansOfType = this.getProxies();
		contextIds = contextManager.getContextIds();
		if(beansOfType.size()>0){
			Set<String> keySet = beansOfType.keySet();
			
			Iterator<String> iterator = keySet.iterator();
			while(iterator.hasNext()){
				GenericProxy next = beansOfType.get(iterator.next());
				getRolesBySingleObject(next);
			}
			
		}
	}

	@SuppressWarnings("unchecked")
	private void getRolesBySingleObject(GenericProxy obj){
		String typeClass = obj.getTypeClass();
		
		List<String> list = null;
		for(Integer cid : contextIds){
			if(roleByContext.containsKey(cid)){
				list = roleByContext.get(cid);
			}else{
				list = new ArrayList<String>();
				roleByContext.put(cid, list);
			}
			for(ObsidianOperations op : ObsidianOperations.values()){
				list.add( constructRole(typeClass, op, cid) );
			}
		}
	}
	
	public String constructRole(String typeClass, ObsidianOperations op, Integer context){
		return ("ROLE_" + typeClass + "#" + op + "#" + context).toUpperCase();
	}
	
	public String constructRole(String typeClass, Object ... params){
		ObsidianOperations op = (ObsidianOperations) params[0];
		Integer context = (Integer) params[1];
		return constructRole(typeClass, op, context);
	}
	
	
	
	/**
	 * @return the iContextManager
	 */
	public IContextManager getContextManager() {
		return contextManager;
	}


	/**
	 * @param iContextManager the iContextManager to set
	 */
	public void setContextManager(IContextManager iContextManager) {
		this.contextManager = iContextManager;
	}

	@Override
	public Map<String, Map<String, String>> getDataForAuth() {
		return null;
	}	


}
